<template>
  <div class="drag-box">
    {{ dragTargets }}
    <hr>
    {{ list }}
    <div class="drag-area" v-drag-area style="border: solid;">

      <div class="drag" v-for=" li in list" v-drag :id="li.id" :key="li.id"> <button
          @click="fullscreen(li.id, $event)">全屏</button><button @click="del(li.id)">删除</button>
      </div>

    </div>
    <div class="drag-target">
      <div v-for=" dt in dragTargets " :key="dt.id" class="target" :id="dt.id" v-drag-target></div>
    </div>
  </div>
</template>
  
<script>
let dragAreaLeft = 0;
let dragAreaTop = 0;

let dragAreaWidth = 0;
let dragAreaHeight = 0;

import { v4 as uuidv4 } from 'uuid';

export default {
  data() {
    return {
      list: [{ id: uuidv4(), store: false }],
      dragTargets: [
        { id: uuidv4(), targetId: '' },
        { id: uuidv4(), targetId: '' },
        { id: uuidv4(), targetId: '' },
      ]
    }
  },
  directives: {
    drag: {
      inserted: (el, bind, vnode) => {
        el.draggable = true;
        // 移动的目标
        el.ondragstart = function (e) {
          const id = e.target.id;
          e.dataTransfer.setData("targetId", id);

          // 隐藏原标签
          setTimeout(() => {
            this.style.display = 'none'
          })
          // 获取鼠标偏差
          const bc = el.getBoundingClientRect()
          const px = e.pageX - bc.left
          const py = e.pageY - bc.top

          // 移动
          el.ondrag = function (e) {
            e.preventDefault()
            // 小盒子取消移动 只在大盒子中移动
            if (vnode.context.list.find(el => el.id === id && el.store)) return;

            const x = e.pageX;
            const y = e.pageY;
            if (x + y !== 0) {
              let left = x - dragAreaLeft + window.pageXOffset - px;
              let top = y - dragAreaTop + window.pageYOffset - py;


              // 超出范围就移到中间
              // if (left <= 0 || top <= 0 || left > dragAreaWidth || top > dragAreaHeight) {

              //   const { width, height } = getComputedStyle(el);
              //   left = (dragAreaWidth - parseInt(width)) / 2
              //   top = (dragAreaHeight - parseInt(height)) / 2

              //   console.log();
              // }

              // 超出范围就移到边界
              if (left < 0) left = 0;
              if (top < 0) top = 0;
              const { width, height } = getComputedStyle(el);
              if (left > dragAreaWidth - parseInt(width)) left = dragAreaWidth - parseInt(width)
              if (top > dragAreaHeight - parseInt(height)) top = dragAreaHeight - parseInt(height)

              // 移动
              el.style.left = left + 'px';
              el.style.top = top + 'px';

            }
          }
        }
        el.ondragend = (e) => {
          // 结束后显示
          el.style.display = ''
        }

      },
    },
    // 三个小盒子
    dragTarget: {
      bind: (el, bind, vnode) => {
        // 允许 ondrop
        el.ondragover = (e) => e.preventDefault();
        el.ondragenter = function (e) { }
        el.ondragleave = function (e) { }

        el.ondrop = function (e) {
          // 获取拖拽的DOM
          const targetId = e.dataTransfer.getData("targetId");
          const dragDom = document.getElementById(targetId);

          // 禁止小盒子间拖拽
          // const inDragTargets = vnode.context.dragTargets.find(item => item.targetId === targetId);
          // if (inDragTargets) return;

          // 一个小盒子只能放一个
          // 保存targetId，保存前先删除之前的所有保存
          // 删除之前的所有保存
          vnode.context.dragTargets.filter(item => item.targetId === targetId).forEach(obj => {
            obj.targetId = '';
          });
          const obj = vnode.context.dragTargets.find(item => item.id === this.id);
          if (obj.targetId) return
          obj.targetId = targetId

          // 标记已存储
          vnode.context.list.find(el => el.id === targetId).store = true

          // 拖入到小盒子，调整定位
          el.append(dragDom);
          dragDom.style = '';
          dragDom.style.position = 'static';

        }
      },
    },
    // 一个大盒子
    dragArea: {

      inserted: (el, bind, vnode) => {
        // 获取距离 left,top
        dragAreaLeft = el.offsetLeft;
        dragAreaTop = el.offsetTop;

        // 获取宽高
        dragAreaWidth = el.offsetWidth;
        dragAreaHeight = el.offsetHeight


        // 允许 ondrop
        el.ondragover = (e) => e.preventDefault();

        el.ondrop = function (e) {
          // 大盒子只允许存在一个
          if (vnode.context.list.find(el => el.store === false)) return;

          // 获取拖拽的DOM
          const targetId = e.dataTransfer.getData("targetId");

          const dragDom = document.getElementById(targetId);

          // 拖入到大盒子，调整定位     
          el.append(dragDom);
          dragDom.style.position = 'absolute'
          dragDom.style.zIndex = 99999


          // 删除targetId
          const obj = vnode.context.dragTargets.find(item => item.targetId === targetId);
          if (obj) obj.targetId = '';

          // 标记未存储
          vnode.context.list.find(el => el.id === targetId).store = false

          // 定位坐标
          // const x = e.pageX;
          // const y = e.pageY;

          // dragDom.style.top = y - dragAreaTop - 50 + 'px'
          // dragDom.style.left = x - dragAreaLeft - 50 + 'px'

        }
      },
    }
  },
  methods: {
    fullscreen(id, e) {
      const el = document.getElementById(id);
      if (el.classList.contains('fullscreen')) {
        el.style.position = 'absolute';
        el.classList.remove('fullscreen');
        el.draggable = true
        e.target.innerHTML = '全屏'
      } else {
        el.style = ''
        el.style.position = 'fixed';
        el.classList.add('fullscreen');
        el.draggable = false
        e.target.innerHTML = '取消全屏'
      }
    },

    add() {
      // 大盒子只允许存在一个
      if (this.list.find(el => el.store === false)) return;

      this.list.push({ id: uuidv4(), store: false })
    },

    del(id) {
      this.list.splice(this.list.findIndex(el => el.id === id), 1);
      const obj = this.dragTargets.find(el => el.targetId === id);
      if (obj) obj.targetId = ''
    }

  }
}
</script>
<style lang="scss" scoped>
.drag-box {
  .drag-area {
    height: 400px;
    width: 600px;
    position: absolute;
    overflow: hidden;
    left: 220px;
    top: 120px;

    .drag {
      position: absolute;
      width: 100px;
      height: 100px;
      background: yellow;
      z-index: 99999;
      top: calc(50% - 50px);
      left: calc(50% - 50px);
    }

    // 全屏
    .fullscreen {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: auto;
      height: auto;
      z-index: 99999
    }
  }

  .drag-target {
    width: 200px;
    position: absolute;
    top: 200px;



    .target {
      position: relative;
      height: 180px;
      border: solid;

      .drag {
        position: absolute;
        width: 100px;
        height: 100px;
        background: yellow;
      }

      // 全屏
      .fullscreen {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        width: auto;
        height: auto;
        z-index: 99999
      }
    }
  }
}
</style>